package com.bytes32.preprocess;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bytes32.classification.tree.dataset.Feature;
import com.bytes32.classification.tree.dataset.InvalidFeatureValueException;
import com.bytes32.parsing.Parser;
import com.bytes32.parsing.ParsingException;
import com.bytes32.parsing.TypeEvaluator;

public class FeatureBuilder {

	/**
	 * Default Logger
	 */
	private final static Logger LOG = LoggerFactory.getLogger(FeatureBuilder.class);

	private Feature result;

	private boolean done = false;

	private final Object[] buffer;

	private int pos = 0;

	private final int confidence;

	private final List<Parser> parsers;
	
	/**
	 * Constructor
	 * @param max
	 *  the number of items to evaluate
	 * @param confidence
	 *  how many successful hits will a parser
	 *  need in order to be elected
	 *  @param parsers
	 *  the list of parsers sorted by weight
	 */
	public FeatureBuilder(int max, int confidence,List<Parser> parsers) {
		buffer = new Object[max];
		this.confidence = confidence;
		this.parsers = parsers;
	}

	
	
	public FeatureBuilder evaluate(Object value) throws ParsingException {
		if (done)
			throw new IllegalStateException("Feature is already determined");
		if (pos < buffer.length) {
			this.buffer[pos] = value;
			pos += 1;
		} else {
			build();
		}	
		return this;
	}

	public Feature build() throws ParsingException {
		if (result != null && done)
			return result;
		/* build the thing */
		/* the buffer is full */
		Parser win = TypeEvaluator.parseAndReset(buffer, parsers, confidence);

		result = new Feature();
		result.setAttributeType(win.getAttributeType());
		result.setFeatureType(win.getFeatureType());
		result.setParserId(win.getId());
		for (int i = 0; i < pos; i++){
			/* add every item to the feature */
			try {
				result.incrementCount(win.intoText(this.buffer[i]));
			} catch (InvalidFeatureValueException e) {
				if (LOG.isDebugEnabled())
					LOG.debug(" Unable to increment feature ",e);
			} catch (ParsingException e) {
				LOG.error(" Unable to decode feature ["+this.buffer[i]+"]");
			}
		}
		done = true;
		return result;
	}

}
